package org.dreamwork.tools.code.analyzer;

import org.dreamwork.cli.text.Alignment;
import org.dreamwork.cli.text.TextFormatter;
import org.dreamwork.tools.code.analyzer.core.FileStatistician;
import org.dreamwork.tools.code.analyzer.core.ModuleStatisticInfo;
import org.dreamwork.tools.code.analyzer.core.ModuleWalker;
import org.dreamwork.util.FileInfo;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CliMain {
    private static long totalLines = 0;
    public static void main (String[] args) throws Exception {
        {
            Pattern VERSION = Pattern.compile ("^([vV])?([\\d]+)\\.([\\d]+)\\.([\\d]+)$");
            String[] texts = {"V2", "1", "v3.0.0", "V3.1.4", "4.0.0", "4.1.2", "4.2.0"};
            for (String text : texts) {
                Matcher m = VERSION.matcher (text);
                if (m.matches ()) {
                    int x = Integer.parseInt (m.group (2));
                    int y = Integer.parseInt (m.group (3));
                    int z = Integer.parseInt (m.group (4));
                    System.out.printf ("x = %d, y = %d, z = %d%n", x, y, z);
                } else {
                    System.out.printf ("%s not matched.%n", text);
                }
            }
        }



        String dirName = "D:\\hothink\\iot-cloud\\modules\\monitor-center";
        String ignores = ".git/;target/;src/main/webapp/;*.iml;.gitignore;*.otf;*.ttf;*.png;*.eot;*.woff2;*.svg;*.xlsx;*.woff";
        Path root = Paths.get (dirName);

        System.out.printf ("counting %s...%n", root.toAbsolutePath ());
        ModuleWalker walker = new ModuleWalker (root);
        ModuleStatisticInfo info = walker.setIgnoredPattern (ignores).walk ();
        System.out.printf ("total %,3d dirs, %,3d files.%n", info.getTotalDirs (), info.getTotalFiles ());
        System.out.printf ("%,3d dirs ignored, %,3d files ignored.%n", info.getIgnoredDirs ().size (), info.getIgnoredFiles ().size ());
        System.out.printf ("ignore pattern: %s%n", ignores);
//        System.out.printf ("  %,3d files to analyze%n", info.getTarget ().size ());
        if (!info.getTarget ().isEmpty ()) {
            List<Path> files = info.getTarget ();
            long total = 0, size = 0;
            Map<String, Long> dict = new HashMap<> ();
            for (Path file : files) {
                String fileName = file.toAbsolutePath ().toString ();
                FileStatistician fs = new FileStatistician (fileName);
                fs.statistics ();
                total += fs.getCrlf ();
                size += fs.getTotal ();
                String type = FileInfo.getExtension (fileName);
                Long count = dict.computeIfAbsent (type, key -> 0L);
                dict.put (type, count + fs.getCrlf ());
            }

            System.out.printf ("total %,3d bytes, %,3d lines.%n", size, total);
            String[][] data = new String[dict.size ()][2];
            Alignment[] alignments = {Alignment.Left, Alignment.Right};
            int pos = 0;
            for (Map.Entry<String, Long> e : dict.entrySet ()) {
                data[pos][0] = e.getKey ();
                data[pos][1] = String.format ("%,3d", e.getValue ());
                pos ++;
            }
            TextFormatter.printTable (System.out, data, null, alignments, false);
        }
/*
        Set<PathFilter> ignoredDirs = new HashSet<> ();
        Set<PathFilter> ignoredFiles = new HashSet<> ();
        String[] a = ignores.split (";");
        for (String p : a) {
            if (StringUtil.isEmpty (p)) continue;

            p = p.trim ().replace ('\\', '/');
            if (p.endsWith ("/")) {
                p = p.substring (0, p.length () - 1);
                ignoredDirs.add (new PathFilter (p));
            } else {
                ignoredFiles.add (new PathFilter (p));
            }
        }

        int[] counter = new int[2];
        List<Path> list = new ArrayList<> ();
        FileVisitor<Path> visitor = new SimpleFileVisitor<Path> () {
            @Override
            public FileVisitResult preVisitDirectory (Path path, BasicFileAttributes basicFileAttributes) {
                if (path.equals (root)) return FileVisitResult.CONTINUE;

                String p = root.relativize (path).toString ();
                if (!StringUtil.isEmpty (p)) {
                    p = p.replace ('\\', '/');
                }
                for (PathFilter f : ignoredDirs) {
                    if (f.hit (p)) {
                        System.out.println ("dir " + p + " is ignored");
                        return FileVisitResult.SKIP_SUBTREE;
                    }
                }
                counter[0] ++;
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile (Path path, BasicFileAttributes attrs) {
                String p = root.relativize (path).toString ();
                for (PathFilter f : ignoredFiles) {
                    if (f.hit (p)) {
                        System.out.println ("file " + p + " is ignored.");
                        return FileVisitResult.CONTINUE;
                    }
                }
                counter[1] ++;
                list.add (path);
                return FileVisitResult.CONTINUE;
            }
        };
        Files.walkFileTree (root, visitor);
        System.out.printf ("directories: %,3d%n", counter[0]);
        System.out.printf ("files      : %,3d%n", counter[1]);
        System.out.println (list.size ());
        Map<String, Long> categories = new HashMap<> ();
        if (!list.isEmpty ()) {
            list.sort (Path::compareTo);
            TaskGroup<Path> group = new TaskGroup<> ("g", counter[1], 4);
            CountDownLatch latch = new CountDownLatch (counter[1]);
            group.start (file -> {
                try {
                    FileStatistician fs = new FileStatistician (file.toAbsolutePath ().toString ());
                    fs.statistics ();
                    totalLines += fs.getLf ();
                    String ext = FileInfo.getExtension (file.toString ());
                    Long count = categories.computeIfAbsent (ext, key -> 0L);
                    categories.put (ext, count + fs.getLf ());
                } catch (IOException ex) {
                    ex.printStackTrace ();
                } finally {
                    latch.countDown ();
                }
            });
            long start = System.currentTimeMillis ();
            list.parallelStream ().forEach (group::offer);
            latch.await ();
            long end = System.currentTimeMillis ();
            group.destroy ();
            System.out.printf ("total %,3d lines, takes %,3d ms.%n", totalLines, end - start);
            categories.forEach ((type, count) -> {
                System.out.printf ("%s\t\t\t%,3d%n", type, count);
            });
        }
*/
    }
}